#include "HiranipraShared.h"

#include "HCM/IComponent.h"

#ifndef _SHARED_PLATFORM_GRAPHICS_IBUFFER_H_
#define _SHARED_PLATFORM_GRAPHICS_IBUFFER_H_

namespace Hiranipra {
	namespace Platform {
		namespace Graphics {

			enum BufferFlags
			{ 
				BufferDynamic		= 0x00000001,
				BufferStatic		= 0x00000002,
				BufferReadAccess	= 0x00000004,
				BufferWriteAccess	= 0x00000008,
				BufferSystemMemory	= 0x00000010,
				BufferVideoMemory	= 0x00000020,
				BufferDefault		= ( BufferStatic | BufferWriteAccess ),
			};

			enum UploadPolicy
			{
				UploadOnUnlock,
				UploadOnRender,
			};

			enum LockFlags
			{
				LockRead			= 0x00000001,
				LockWrite			= 0x00000002,
				LockNoUpload		= 0x00000004,
				LockForceUpload		= 0x00000008,
			};

			class IBuffer : implements RefInstance
			{
			public:
				IBuffer( const BufferFlags flags, uint32 elementCount, uint32 elementSize ) :
					_flags( flags ), _elementCount( elementCount ), _elementSize( elementSize ),
					_uploadPolicy( UploadOnUnlock ),
					_isLocked( false ), _isDirty( true )
				{
				}
				virtual ~IBuffer() {}

				virtual BufferFlags GetFlags() const { return _flags; }

				virtual UploadPolicy GetUploadPolicy() const { return _uploadPolicy; }
				virtual void SetUploadPolicy( const UploadPolicy uploadPolicy ) { _uploadPolicy = uploadPolicy; }

				virtual void Lock( const LockFlags lockFlags )
				{
					_lock.acquire();
					_isLocked = true;
					_lockFlags = lockFlags;
				}

				virtual void Unlock()
				{
					ASSERT( _isLocked == true, "Unmatched Unlock()" );
					_isLocked = false;
					_lock.release();

					if( ( _isDirty == true ) && ( _uploadPolicy == UploadOnUnlock ) )
						this->Upload();
				}

				virtual bool Upload()
				{
					if( _isDirty == false )
						return false;
					_isDirty = false;
					return true;
				}

				uint32 GetSize() const { return _elementCount * _elementSize; }
				uint32 GetElementCount() const { return _elementCount; }
				uint32 GetElementSize() const { return _elementSize; }

				bool IsLocked() const { return _isLocked; }
				bool IsDirty() const { return _isDirty; }

				virtual bool GetData( void* buffer, uint32 startIndex, uint32 elementCount ) const = 0;
				virtual void SetData( const void* buffer, uint32 startIndex, uint32 elementCount, bool discard ) = 0;

			protected:
				BufferFlags		_flags;
				uint32			_elementCount;
				uint32			_elementSize;
				UploadPolicy	_uploadPolicy;
				bool			_isLocked;
				LockFlags		_lockFlags;
				FastMutex		_lock;
				bool			_isDirty;
			};

		}
	}
}

#endif // _SHARED_PLATFORM_GRAPHICS_IBUFFER_H_
